package com.heihu577.bean;


import com.aliyun.oss.ClientConfiguration;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.DefaultCredentialProvider;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import com.aliyun.oss.common.comm.NoRetryStrategy;
import com.aliyun.oss.model.ObjectListing;
import com.aliyun.oss.model.PutObjectResult;
import com.heihu577.controller.MyAppController;
import com.heihu577.util.FileUtils;
import com.heihu577.util.UploadUtils;
import javafx.application.Platform;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.VBox;
import javafx.stage.Window;

import java.io.File;
import java.net.SocketException;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class AliyunOSSBean {
    public static String ACCESS_KEY_ID;
    public static String ACCESS_KEY_SECRET;
    public static String ENDPOINT;
    public static String BUCKET_NAME;
    public static String configFile = "AliyunOSS";
    /**
     * 包含: file -> File
     * properties -> Properties
     * fileInputStream -> FileInputStream
     */
    public static Map<String, Object> fileInfo;
    // OSS 客户端
    private static OSS ossClient;
    // 当前线程, 主要是处理解析图片时所用
    public Thread nowThread;
    // 增加一个状态
    public StringBuffer resultMd = new StringBuffer();

    // 初始化方法, 调用一次, 更新一次 Bean 状态
    public static void initBean() {
        try {
            fileInfo = FileUtils.getPropertiesFileInputStreamFileOutputStream(configFile);
            Properties properties = (Properties) fileInfo.get("properties");
            AliyunOSSBean.ACCESS_KEY_ID = properties.getProperty("ACCESS_KEY_ID");
            AliyunOSSBean.ACCESS_KEY_SECRET = properties.getProperty("ACCESS_KEY_SECRET");
            AliyunOSSBean.ENDPOINT = properties.getProperty("ENDPOINT");
            AliyunOSSBean.BUCKET_NAME = properties.getProperty("BUCKET_NAME");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    // 判断当前 OSS 是否可以连接的上
    public static boolean checkStatus() {
        if (ACCESS_KEY_ID != null && ACCESS_KEY_SECRET != null && ENDPOINT != null && BUCKET_NAME != null) {
            DefaultCredentialProvider credentialsProvider = CredentialsProviderFactory.newDefaultCredentialProvider(ACCESS_KEY_ID, ACCESS_KEY_SECRET);
            ClientConfiguration clientConfiguration = new ClientConfiguration();
            clientConfiguration.setConnectionTimeout(5000); // 5秒超时设置
            clientConfiguration.setSocketTimeout(10000); // 读取超时时间
            clientConfiguration.setRetryStrategy(new NoRetryStrategy()); // 超时不重连
            // 设置最大连接数
            clientConfiguration.setMaxConnections(100); // 根据需要调整这个值
            ossClient = OSSClientBuilder.create().clientConfiguration(clientConfiguration).endpoint(ENDPOINT).credentialsProvider(credentialsProvider).build();
            try {
                ossClient.listObjects(BUCKET_NAME);
                return true;
            } catch (Exception e) {
                // OSS 链接失败
                return false;
            }
        }
        return false;
    }

    // 通过 MarkdownFile, 解析出图片, 并上传到 OSS.
    // 老版本, 会导致阻塞问题, 已废弃
    public void uploadByMarkdownFile(MarkdownFile markdownFile, MyAppController myAppController) {
//        nowThread = new Thread(() -> {
//            String parent = markdownFile.getFile().getParent(); // 得到父目录
//            Map<String, String> urls = markdownFile.getUrls(); // 得到所有图片
//            Set<Map.Entry<String, String>> entries = urls.entrySet();
//            for (Map.Entry<String, String> entry : entries) {
//                String key = entry.getKey(); // 图片在markdown中的名称
//                String value = entry.getValue(); // 图片相对路径
//                File file = new File(parent, value);
//                // 图片上传
//                ossClient.putObject(BUCKET_NAME, value, file);
//            }
//            // 准备替换, 匹配了两次, 这里将上次匹配到的, 作为这次的修改
//            Pattern compile = Pattern.compile(MarkdownFile.IMAGE_PATTERN, Pattern.MULTILINE);
//            Matcher matcher = compile.matcher(markdownFile.getContent());
//
//            while (matcher.find()) { // 开始查找
//                String fileName = matcher.group(3);
//                String URL = "https://" + BUCKET_NAME + "." + ENDPOINT + "/" + fileName;
//                Platform.runLater(() -> {
//                    // 操作 UI 之前, 在这里一定要用 Platform.runLater 进行处理!
//                    myAppController.printToLog("[+] Upload " + fileName + " -> " + URL);
//                });
//                // " + matcher.group(1) + ", 删掉这个了, 以免在公众号碍眼
//                matcher.appendReplacement(resultMd, "![](" + URL + ")");
//            }
//            // 将末尾追加进去
//            matcher.appendTail(resultMd);
//        });
//        nowThread.start();
    }

    // 上传文件, 并弹出窗口
    public void uploadByMarkdownFile2(MarkdownFile markdownFile, MyAppController myAppController, VBox vbox, ProgressBar progressBar, Window window) {
        UploadUtils.UploadByAliyunOSSTask uploadByAliyunOSSTask = new UploadUtils.UploadByAliyunOSSTask(markdownFile, myAppController, ossClient, vbox, progressBar, window, this);
        uploadByAliyunOSSTask.progressProperty().addListener((observable, oldValue, newValue) -> {
            // 用于更新进度条信息
            progressBar.setProgress(newValue.doubleValue());
        });
        // 当 updateMessage 之后, 我们的 Task 做什么样的动作, 这里不能太快, 如果太快则可能导致监听不到. 所以在 OSS 上传完毕后进行监听
        uploadByAliyunOSSTask.messageProperty().addListener((observable, oldValue, newValue) -> {
            // System.out.println(newValue);
            // 利用传递过来的 myAppController 控件定义的方法, 用于在 log 中插入值.
            myAppController.printToLog(newValue); // 监听 updateMessage 传递的内容, 监听到后输出到当前 UI 界面
        });
        new Thread(uploadByAliyunOSSTask).start();
    }

    // 删除文件, 并写入日志
    public void deleteFileByList(MarkdownFile markdownFile, MyAppController myAppController, List<String> files) {
        UploadUtils.DeleteByAliyunOSSTask deleteByAliyunOSSTask = new UploadUtils.DeleteByAliyunOSSTask(myAppController, markdownFile, ossClient, this, files);
        deleteByAliyunOSSTask.messageProperty().addListener((observable, oldValue, newValue) -> myAppController.printToLog(newValue)); // 打印日志事件
        new Thread(deleteByAliyunOSSTask).start();
    }
}

